package com.bkhech.nettyhttp.server;

import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;

import javax.net.ssl.KeyManagerFactory;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;

/**
 * SslContextFactoryForServer
 * 服务器端生产环境中需安全的证书管理策略示例
 * <p>
 * 单向验证: 服务端不需要 TrustManagerFactory，
 * 单向验证，即服务端开启了https验证，验证客户端的请求，
 * 双向验证中如果客户端也开启了https验证，则需要将客户端的证书存放到 TrustManagerFactory
 *
 * @author guowm
 * @date 2024/4/1
 */
public class SslContextFactoryForServer {

    //Java特有的密钥存储格式
    private static final String KEY_STORE_TYPE = "JKS";
    // Bouncy Castle 的 X.509 证书管理器。
    private static final String KEY_MANAGER_TYPE = "X509";
    //JKS 格式的服务器证书的实际路径。
    private static final String KEY_STORE_PATH = "/path/to/your/server.jks";
    //JKS 格式的服务器证书的密码。
    private static final String KEY_STORE_PASSWORD = "your_keystore_password";

    public static SslContext getSslContext() throws Exception {
        KeyManagerFactory keyManagerFactory = buildKeyManagerFactory();
        return SslContextBuilder.forServer(keyManagerFactory).build();
    }

    private static KeyManagerFactory buildKeyManagerFactory() throws Exception {
        KeyStore keyStore = loadKeyStore(KEY_STORE_PATH, KEY_STORE_PASSWORD);
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER_TYPE);
        keyManagerFactory.init(keyStore, KEY_STORE_PASSWORD.toCharArray());
        return keyManagerFactory;
    }

    private static KeyStore loadKeyStore(String storePath, String storePassword) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
        KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
        try (FileInputStream fis = new FileInputStream(storePath)) {
            keyStore.load(fis, storePassword.toCharArray());
        }
        return keyStore;
    }
}
